package sy6_Behavioral_Pattern.iterator;

import java.util.ArrayList;
import java.util.List;
/**
 * 迭代器模式(Iterator Pattern)提供一种方法来访问聚合对象，而不用暴露这个对象的内部表示
 * 迭代器模式是单一职责原则的完美体现
 *
 * Aggregate作为抽象聚合类，定义了创建迭代器的抽象方法
 * Iterator是迭代器接口，定义了遍历集合的若干抽象方法
 * 客户端同时关系 Aggregate和 Iterator
 *
 * ConcreteAggregate是具体聚合类，继承Aggregate，依赖 ConcreteIterator
 * ConcreteIterator是具体迭代器类，继承 Iterator，关联 ConcreteAggregate
 *
 * 可以将抽象的 Aggregate和 Iterator，设计为接口
 */
abstract class Aggregate { //角色1：抽象聚合类
	//抽象聚合类必须定义的方法
	public abstract Iterator createIterator();
}

abstract class Iterator { //角色2：迭代器接口
	protected abstract  boolean hasNext(); //还有下一个元素吗？
	protected abstract  Object getNextItem();  //获取下一个元素（通用类型）
	protected abstract  void next(); //指向下一个元素位置
}

class ConcreteAggregate extends Aggregate { //角色3：具体聚合类

	private List<String> list=new ArrayList<String>();  //实例化

	public List<String> getList(){  //getter
		return list;
	}

	@Override
	public Iterator createIterator() { //重写基类方法
		//根据聚合对象创建迭代器对象【将自身对象作为参数传递给迭代器构造方法】，ConcreteAggregate依赖ConcreteIterator
		return new ConcreteIterator(this);  //返回抽象类型Iterator对象
	}
}

class ConcreteIterator extends Iterator { //角色4：具体迭代器类

	private ConcreteAggregate concreteAggregate;  //聚合
	private int cursor; //定义一个用于正向遍历的游标（元素位置指针）

	//体现 ConcreteIterator对 ConcreteAggregate作为参数的关联
	public ConcreteIterator(ConcreteAggregate concreteAggregate) {   //构造器注入
		this.concreteAggregate=concreteAggregate;
		cursor=0; //设置初始值
	}

	@Override
	public void next() {
		if (cursor<concreteAggregate.getList().size()) {
			cursor++;
		}
	}

	@Override
	public boolean hasNext() {
		return (cursor<concreteAggregate.getList().size());
	}

	@Override
	public Object getNextItem() {
		return concreteAggregate.getList().get(cursor);
	}
}

public class Client {  //客户端
	public static void main(String[] args) {
		//创建具体聚合对象
		ConcreteAggregate aggregate = new ConcreteAggregate();
		List<String> list=aggregate.getList();  //具体聚合类的 Getter
		list.add("计算机科学与技术\n");
		list.add("软件工程\n");
		list.add("网络工程\n");
		//创建具体迭代器对象
		Iterator iterator = aggregate.createIterator();
		//遍历
		while(iterator.hasNext()) {
			System.out.print((iterator.getNextItem()));
			iterator.next();
		}
	}
}
